home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / HTMLParser.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  11KB  |  336 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''A parser for HTML and XHTML.'''
  5. import markupbase
  6. import re
  7. interesting_normal = re.compile('[&<]')
  8. interesting_cdata = re.compile('<(/|\\Z)')
  9. incomplete = re.compile('&[a-zA-Z#]')
  10. entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
  11. charref = re.compile('&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]')
  12. starttagopen = re.compile('<[a-zA-Z]')
  13. piclose = re.compile('>')
  14. commentclose = re.compile('--\\s*>')
  15. tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*')
  16. attrfind = re.compile('\\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\\s*=\\s*(\\\'[^\\\']*\\\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\\(\\)_#=~@]*))?')
  17. locatestarttagend = re.compile('\n  <[a-zA-Z][-.a-zA-Z0-9:_]*          # tag name\n  (?:\\s+                             # whitespace before attribute name\n    (?:[a-zA-Z_][-.:a-zA-Z0-9_]*     # attribute name\n      (?:\\s*=\\s*                     # value indicator\n        (?:\'[^\']*\'                   # LITA-enclosed value\n          |\\"[^\\"]*\\"                # LIT-enclosed value\n          |[^\'\\">\\s]+                # bare value\n         )\n       )?\n     )\n   )*\n  \\s*                                # trailing whitespace\n', re.VERBOSE)
  18. endendtag = re.compile('>')
  19. endtagfind = re.compile('</\\s*([a-zA-Z][-.a-zA-Z0-9:_]*)\\s*>')
  20.  
  21. class HTMLParseError(Exception):
  22.     '''Exception raised for all parse errors.'''
  23.     
  24.     def __init__(self, msg, position = (None, None)):
  25.         if not msg:
  26.             raise AssertionError
  27.         self.msg = msg
  28.         self.lineno = position[0]
  29.         self.offset = position[1]
  30.  
  31.     
  32.     def __str__(self):
  33.         result = self.msg
  34.         if self.lineno is not None:
  35.             result = result + ', at line %d' % self.lineno
  36.         
  37.         if self.offset is not None:
  38.             result = result + ', column %d' % (self.offset + 1)
  39.         
  40.         return result
  41.  
  42.  
  43.  
  44. class HTMLParser(markupbase.ParserBase):
  45.     '''Find tags and other markup and call handler functions.
  46.  
  47.     Usage:
  48.         p = HTMLParser()
  49.         p.feed(data)
  50.         ...
  51.         p.close()
  52.  
  53.     Start tags are handled by calling self.handle_starttag() or
  54.     self.handle_startendtag(); end tags by self.handle_endtag().  The
  55.     data between tags is passed from the parser to the derived class
  56.     by calling self.handle_data() with the data as argument (the data
  57.     may be split up in arbitrary chunks).  Entity references are
  58.     passed by calling self.handle_entityref() with the entity
  59.     reference as the argument.  Numeric character references are
  60.     passed to self.handle_charref() with the string containing the
  61.     reference as the argument.
  62.     '''
  63.     CDATA_CONTENT_ELEMENTS = ('script', 'style')
  64.     
  65.     def __init__(self):
  66.         '''Initialize and reset this instance.'''
  67.         self.reset()
  68.  
  69.     
  70.     def reset(self):
  71.         '''Reset this instance.  Loses all unprocessed data.'''
  72.         self.rawdata = ''
  73.         self.lasttag = '???'
  74.         self.interesting = interesting_normal
  75.         markupbase.ParserBase.reset(self)
  76.  
  77.     
  78.     def feed(self, data):
  79.         """Feed data to the parser.
  80.  
  81.         Call this as often as you want, with as little or as much text
  82.         as you want (may include '
  83. ').
  84.         """
  85.         self.rawdata = self.rawdata + data
  86.         self.goahead(0)
  87.  
  88.     
  89.     def close(self):
  90.         '''Handle any buffered data.'''
  91.         self.goahead(1)
  92.  
  93.     
  94.     def error(self, message):
  95.         raise HTMLParseError(message, self.getpos())
  96.  
  97.     __starttag_text = None
  98.     
  99.     def get_starttag_text(self):
  100.         """Return full source of start tag: '<...>'."""
  101.         return self._HTMLParser__starttag_text
  102.  
  103.     
  104.     def set_cdata_mode(self):
  105.         self.interesting = interesting_cdata
  106.  
  107.     
  108.     def clear_cdata_mode(self):
  109.         self.interesting = interesting_normal
  110.  
  111.     
  112.     def goahead(self, end):
  113.         rawdata = self.rawdata
  114.         i = 0
  115.         n = len(rawdata)
  116.         while i < n:
  117.             match = self.interesting.search(rawdata, i)
  118.             if match:
  119.                 j = match.start()
  120.             else:
  121.                 j = n
  122.             if i < j:
  123.                 self.handle_data(rawdata[i:j])
  124.             
  125.             i = self.updatepos(i, j)
  126.             if i == n:
  127.                 break
  128.             
  129.             startswith = rawdata.startswith
  130.             None if startswith('<', i) else match
  131.             if startswith('&', i):
  132.                 match = entityref.match(rawdata, i)
  133.                 if match:
  134.                     name = match.group(1)
  135.                     self.handle_entityref(name)
  136.                     k = match.end()
  137.                     if not startswith(';', k - 1):
  138.                         k = k - 1
  139.                     
  140.                     i = self.updatepos(i, k)
  141.                     continue
  142.                 
  143.                 match = incomplete.match(rawdata, i)
  144.                 if match:
  145.                     if end and match.group() == rawdata[i:]:
  146.                         self.error('EOF in middle of entity or char ref')
  147.                     
  148.                     break
  149.                 elif i + 1 < n:
  150.                     self.handle_data('&')
  151.                     i = self.updatepos(i, i + 1)
  152.                 else:
  153.                     break
  154.             match
  155.             if not 0:
  156.                 raise AssertionError, 'interesting.search() lied'
  157.         if end and i < n:
  158.             self.handle_data(rawdata[i:n])
  159.             i = self.updatepos(i, n)
  160.         
  161.         self.rawdata = rawdata[i:]
  162.  
  163.     
  164.     def parse_pi(self, i):
  165.         rawdata = self.rawdata
  166.         if not rawdata[i:i + 2] == '<?':
  167.             raise AssertionError, 'unexpected call to parse_pi()'
  168.         match = piclose.search(rawdata, i + 2)
  169.         if not match:
  170.             return -1
  171.         
  172.         j = match.start()
  173.         self.handle_pi(rawdata[i + 2:j])
  174.         j = match.end()
  175.         return j
  176.  
  177.     
  178.     def parse_starttag(self, i):
  179.         self._HTMLParser__starttag_text = None
  180.         endpos = self.check_for_whole_start_tag(i)
  181.         if endpos < 0:
  182.             return endpos
  183.         
  184.         rawdata = self.rawdata
  185.         self._HTMLParser__starttag_text = rawdata[i:endpos]
  186.         attrs = []
  187.         match = tagfind.match(rawdata, i + 1)
  188.         if not match:
  189.             raise AssertionError, 'unexpected call to parse_starttag()'
  190.         k = match.end()
  191.         self.lasttag = tag = rawdata[i + 1:k].lower()
  192.         while k < endpos:
  193.             m = attrfind.match(rawdata, k)
  194.             if not m:
  195.                 break
  196.             
  197.             (attrname, rest, attrvalue) = m.group(1, 2, 3)
  198.             if not rest:
  199.                 attrvalue = None
  200.             elif "'" == "'":
  201.                 pass
  202.             elif not "'" == attrvalue[-1:]:
  203.                 if '"' == '"':
  204.                     pass
  205.                 elif '"' == attrvalue[-1:]:
  206.                     attrvalue = attrvalue[1:-1]
  207.                     attrvalue = self.unescape(attrvalue)
  208.                 
  209.             attrs.append((attrname.lower(), attrvalue))
  210.             k = m.end()
  211.             continue
  212.             attrvalue[:1]
  213.         end = rawdata[k:endpos].strip()
  214.         if end not in ('>', '/>'):
  215.             (lineno, offset) = self.getpos()
  216.             if '\n' in self._HTMLParser__starttag_text:
  217.                 lineno = lineno + self._HTMLParser__starttag_text.count('\n')
  218.                 offset = len(self._HTMLParser__starttag_text) - self._HTMLParser__starttag_text.rfind('\n')
  219.             else:
  220.                 offset = offset + len(self._HTMLParser__starttag_text)
  221.             self.error('junk characters in start tag: %r' % (rawdata[k:endpos][:20],))
  222.         
  223.         if end.endswith('/>'):
  224.             self.handle_startendtag(tag, attrs)
  225.         else:
  226.             self.handle_starttag(tag, attrs)
  227.             if tag in self.CDATA_CONTENT_ELEMENTS:
  228.                 self.set_cdata_mode()
  229.             
  230.         return endpos
  231.  
  232.     
  233.     def check_for_whole_start_tag(self, i):
  234.         rawdata = self.rawdata
  235.         m = locatestarttagend.match(rawdata, i)
  236.         if m:
  237.             j = m.end()
  238.             next = rawdata[j:j + 1]
  239.             if next == '>':
  240.                 return j + 1
  241.             
  242.             if next == '/':
  243.                 if rawdata.startswith('/>', j):
  244.                     return j + 2
  245.                 
  246.                 if rawdata.startswith('/', j):
  247.                     return -1
  248.                 
  249.                 self.updatepos(i, j + 1)
  250.                 self.error('malformed empty start tag')
  251.             
  252.             if next == '':
  253.                 return -1
  254.             
  255.             if next in 'abcdefghijklmnopqrstuvwxyz=/ABCDEFGHIJKLMNOPQRSTUVWXYZ':
  256.                 return -1
  257.             
  258.             self.updatepos(i, j)
  259.             self.error('malformed start tag')
  260.         
  261.         raise AssertionError('we should not get here!')
  262.  
  263.     
  264.     def parse_endtag(self, i):
  265.         rawdata = self.rawdata
  266.         if not rawdata[i:i + 2] == '</':
  267.             raise AssertionError, 'unexpected call to parse_endtag'
  268.         match = endendtag.search(rawdata, i + 1)
  269.         if not match:
  270.             return -1
  271.         
  272.         j = match.end()
  273.         match = endtagfind.match(rawdata, i)
  274.         if not match:
  275.             self.error('bad end tag: %r' % (rawdata[i:j],))
  276.         
  277.         tag = match.group(1)
  278.         self.handle_endtag(tag.lower())
  279.         self.clear_cdata_mode()
  280.         return j
  281.  
  282.     
  283.     def handle_startendtag(self, tag, attrs):
  284.         self.handle_starttag(tag, attrs)
  285.         self.handle_endtag(tag)
  286.  
  287.     
  288.     def handle_starttag(self, tag, attrs):
  289.         pass
  290.  
  291.     
  292.     def handle_endtag(self, tag):
  293.         pass
  294.  
  295.     
  296.     def handle_charref(self, name):
  297.         pass
  298.  
  299.     
  300.     def handle_entityref(self, name):
  301.         pass
  302.  
  303.     
  304.     def handle_data(self, data):
  305.         pass
  306.  
  307.     
  308.     def handle_comment(self, data):
  309.         pass
  310.  
  311.     
  312.     def handle_decl(self, decl):
  313.         pass
  314.  
  315.     
  316.     def handle_pi(self, data):
  317.         pass
  318.  
  319.     
  320.     def unknown_decl(self, data):
  321.         self.error('unknown declaration: %r' % (data,))
  322.  
  323.     
  324.     def unescape(self, s):
  325.         if '&' not in s:
  326.             return s
  327.         
  328.         s = s.replace('<', '<')
  329.         s = s.replace('>', '>')
  330.         s = s.replace(''', "'")
  331.         s = s.replace('"', '"')
  332.         s = s.replace('&', '&')
  333.         return s
  334.  
  335.  
  336.